home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 July: Mac OS SDK / Dev.CD Jul 00 SDK2.toast / Development Kits / Hardware / PowerManager DDK 1.0f1 / Updating Drivers for PM v1.0 < prev   
Encoding:
Text File  |  1999-12-07  |  15.9 KB  |  194 lines  |  [ttro/ttxt]

  1. Updating Native PCI Device Drivers for PCI Power Management Compliance
  2.  
  3.  
  4. Contents
  5.       I.    Introduction
  6.       II.    New PCI Driver Requirements
  7.       III.    Power Handlers
  8.                  A.    Registration
  9.                  B.    Using Power Handlers
  10.       IV.    Overview of Sleep and Wake for PCI Drivers
  11.                  A.    Sleep
  12.                  B.    Wake
  13.                  C.    Potential problems
  14.       V.    Notes
  15.  
  16.  
  17. I.     Introduction
  18. The most recent Apple professional desktop CPU's have the capability to remove power from and/or stop the clocks to the PCI expansion slots when the CPU is put into a Power Management Sleep state.  The implication of this new capability is that all drivers that control the devices present in the expansion slots must be able to recover their device’s functionality once power is restored after a Power Management Wake event.  If any driver is incapable of recovering its device’s functionality, then System Software will not allow power to be removed from the PCI expansion slots and, therefore, the CPU will not be allowed to operate from its standby power supply during the Sleep state.
  19.  
  20. This new power management feature is implemented according to the specifications published by the PCI Special Interest Group for PCI Bus Power Management. (1)(2)
  21.  
  22.  
  23. II.     New PCI Driver Requirements
  24. In order to ensure that the System SW can recover from removing power from the PCI expansion bus, it looks for an indication from all PCI device drivers that each and every driver can recover once PCI bus power has been restored (during Wake).
  25.  
  26. To notify the System Software that a a particular driver can recover successfully from PCI power shut-off, a driver must implement  a new Power Management “Power Handler”, which it must register with the Power Manager when loaded.
  27.  
  28.  
  29. III.    Power Handlers
  30. The Sleep and Wake process for PCI device drivers is now centralized around a new mechanism called a Power Handler.  Power handler support is present in version 2.0 (and later) of the Power Manager.  Power handlers work in a similar way to the traditional SleepQProcs but with the following differences:
  31.  
  32.       • Power handlers are called later in the sleep process and earlier in the 
  33.          wake process compared to the classic SleepQProcs;
  34.       • Power handlers are expected to handle a new variety of sleep and wake messages;
  35.       • CPU interrupts are disabled when a Power handler is called with a 
  36.          kSleepDemand, kDozeDemand, or  kSuspendDemand message; CPU interrupts are 
  37.          not disabled during a kSleepRequest, kDozeRequest, or kSuspendRequest message.
  38.  
  39. A.   Registration
  40. A Driver’s Power Handler is registered via the following API:
  41.  
  42. EXTERN_API_C ( OSStatus )
  43.     AddDevicePowerHandler(    RegEntryIDPtr              regEntryID,
  44.                                           PowerHandlerProcPtr     handler,
  45.                                           UInt32                        refCon,
  46.                                           char*                            deviceType );
  47.  
  48. All four (4) parameters are inputs. 
  49.  
  50.       regEntryID                 pointer to the device’s Name Registry Entry
  51.       handler         pointer to a power handler function (PowerPC code--not a routine descriptor)
  52.       refCon                       optional value passed in; will be passed back to the power handler.
  53.       deviceType*            an optional parameter, where the deviceType is specified, such as “scsi” or “ata”.          
  54.                                            It is easiest and most effective to simply pass NULL as this parameter.  If passing 
  55.                                            NULL, the Power Manager will automatically determine the device type.
  56.                     
  57. Before trying to register a Power Handler by calling AddDevicePowerHandler, be sure that the new Power Manager is available.  By “weak-linking” to the latest version of the DriverServicesLib and comparing AddDevicePowerHandler to kUnresolvedCFragSymbolAddress and only proceeding if the check passes, the driver should be safe:
  58.  
  59. if ( (Ptr)AddDevicePowerHandler != (Ptr)kUnresolvedCFragSymbolAddress )
  60. {
  61.       gAddDevicePwrHandlerExists = true;
  62. }
  63. else
  64. {
  65.       gAddDevicePwrHandlerExists = false;
  66. }
  67.  
  68. “Weak-linking” is accomplished differently depending upon the development system.  Metrowerks offers a checkbox (“Import Weak”) from the Project Inspector window for a particular shared library.  MPW’s PPCLink tool has a “-weaklib name[,name]...” command line option for specifying the import lib name(s) as weak.
  69.  
  70. If a driver is finished with a registered Power Handler, it can be removed by the following PowerManager API method:
  71.  
  72. EXTERN_API_C( OSStatus )
  73.    RemoveDevicePowerHandler( RegEntryIDPtr     regEntryID );
  74.  
  75.  
  76. B.   Using Power Handlers
  77. The prototype for a Power handler is as follows:
  78.  
  79. pascal long
  80. DoDriverPowerManagement(    UInt32                message,
  81.                                            void*                    param,
  82.                                            UInt32                refCon,
  83.                                            RegEntryID*        regEntryID );
  84.  
  85.       message                        indicates what the Power handler needs to do.  Messages that could
  86.                                               be received:
  87.           
  88.                                                          kGetPowerInfo               the Driver should report back what types of
  89.                                                                                                     power features are supported; when this
  90.                                                                                                     message is received, the param is a pointer
  91.                                                                                                     to aDevicePowerInfo structure and should
  92.                                                                                                     be filled in according to the device’s power
  93.                                                                                                     capabilities
  94.                                                          kSleepRequest                PCI devices should complete any pending
  95.                                                                                                     I/O in order to prepare for PCI bus power 
  96.                                                                                                     to be removed. 
  97.                                                          kSleepDemand               PCI devices should save their device
  98.                                                                                                     state.  PCI bus power is about to be removed.
  99.                                                                                                     CPU interrupts are disabled at this stage.
  100.                                                          kSleepWakeUp              PCI devices should restore their device state.
  101.                                                                                                     CPU interrupts are disabled at this stage.                                                                     
  102.                                                          kSleepRevoke                PCI devices should reverse any effects of    an earlier       
  103.                                                                                                     kSleepRequest message.
  104.                                                          kGetPowerLevel            return the device’s current power level.
  105.                                                          kSetPowerLevel             set the device’s current power level.
  106.                                                          kDeviceInitiatedWake  the Driver should report back, via param, if it 
  107.                                                                                                     caused a wake event
  108.                                                          kWakeToDoze                the Driver should perform the same steps as 
  109.                                                                                                     kSleepWakeUp unless it supports a partial wake 
  110.                                                                                                     state. Do NOT ignore or return 
  111.                                                                                                     kPowerMgtMessageNotHandled!
  112.                                                                                                     This message is sent in lieu of kSleepWakeUp in 
  113.                                                                                                     the case of a partial wake.
  114.                                                          kDozeToFullWakeUp  if the Driver handles kWakeToDoze differently                
  115.                                                                                                     from kWakeToSleep then it must perform      
  116.                                                                                                     remaining steps to reach a full wakeup state. 
  117.                                                                                                     Otherwise ignore.
  118.  
  119.       param                           used to pass back information to the caller; in the Power Handler’s case, this
  120.                                              information could be a DevicePowerInfo structure, that should be filled with
  121.                                              appropriate values for the device. See the sample code for an example of a proper 
  122.                                              response. For the kDeviceInitiatedWake it is a simple numeric value indicating if
  123.                                              the device caused the wake event and, if so, how "fully" the Power Mgr should 
  124.                                              wake  the machine.
  125.       refCon                         value that was passed to AddDevicePowerHandler.
  126.       regEntryID                A pointer to the device’s Name Registry Entry
  127.  
  128.  
  129. As with Power Handlers registered by other non-ndrv software, appropriate errors must be returned:
  130.  
  131.       • If csCode or message = kSleepRequest/kDozeRequest/kSuspendRequest and the driver wishes 
  132.          to deny the request, it returns a newly-defined kPowerMgtRequestDenied error to the caller. If not, 
  133.          then the driver returns noErr (as with the high-level classic SleepQProc queue).
  134.       • If csCode or message = kSleepDemand/ kDozeDemand/ kSuspendDemand then any result returned 
  135.          is ignored.
  136.       • Any power management csCode or message not handled by the driver should be indicated by the 
  137.          driver returning kPowerMgtMessageNotHandled.
  138.  
  139.  
  140. IV.     Overview of Sleep and Wake for PCI Drivers
  141. Before the System Software is able to request or demand that a device enter a Sleep state, the driver needs to register a Power Handler with the Power Manager as described above under “Power Handlers”.   Usually, this happens during driver initialization.
  142.  
  143. The Power Handler queue is serviced after the high-level classic SleepQProc queue is serviced.  This is useful for allowing devices to provide functionality to the system (and all registered classic SleepQProcs) until the last possible moment before preparing devices for Sleep.
  144.  
  145. The driver is required, when receiving a kSleepDemand message, to set its device into the D3cold state.  When the PCI bus power cannot be powered off, the Power Manager will send a Power Handler a kDozeRequest and/or kDozeDemand message to put the system into a type of Sleep that we have today for desktops; the PCI bus remains fully powered.  Most PCI slot devices can ignore a kDozeRequest and/or kDozeDemand message since PCI bus power remains On during the Doze state.
  146.  
  147. Apple discourages a driver from setting the device state to D3hot when the Power Manager enters the Doze state.  The hardware does not assert the PCI Bus Segment Reset (RST#) signal to the device when Waking from the Doze state; however, the RST# signal is asserted to the device when Waking from the Sleep state after PCI bus power has been restored.
  148.  
  149.  
  150. A.   Sleep
  151. When the system is about to be put into a Sleep state, the Power Manager will eventually invoke the Power Handler that the driver had previously registered. First, the Power Handler will be asked to provide its power capabilities information in the form of a kGetPowerInfo message. In this case, the “param” parameter is a DevicePowerInfo structure. It has already been filled out with information from the PCI config space (PMIS 1.1). Drivers only need to change information in the structure if there is a need to override the pre-determined hardware values. Then, the Power Handler will be asked, via a kSleepRequest message, to prepare the device for entering the Sleep state.  Note that kSleepRequest messages are processed with CPU interrupts enabled.  The Power Handler must make its best-effort to prepare the device for having power removed; this includes resolving the following:
  152.  
  153.       • Any pending I/O should be completed. 
  154.  
  155.      IMPORTANT: The driver should remain ready to process additional I/O requests until the
  156.      kSleepDemand message is received. Do not suspend any I/O  at kSleepRequest time 
  157.      because a page fault during the sleep process could lead to dead lock.
  158.  
  159. The Power Handler may deny a kSleepRequest message; if any Power Handler denies a kSleepRequest message, all previously invoked PCI Power Handlers will be called again with a kSleepRevoke message to reverse any effects from processing their kSleepRequest message.  When a Power Handler denies a kSleepRequest message, unlike classic SleepQProcs, the Sleep process will continue and the CPU will be put into a Sleep state but with the PCI bus power remaining On.  Unfortunately, when the PCI bus power is On during Sleep the CPU cannot operate with its standby power supply.
  160.  
  161. When the Power handler wishes to deny a kSleepRequest message, it must return the kPowerMgtRequestDenied code.
  162.  
  163. If each PCI Power Handler positively acknowledges the kSleepRequest message, the Power Manager will then send each Power handler a kSleepDemand message. NOTE that CPU interrupts are disabled at this point.  The Power Handler must do the following:
  164.  
  165.          • Again, any pending I/O should be completed and subsequent I/O should be suspended.  
  166.       • The driver's device interrupts should be turned off and an error returned in response to subsequent 
  167.           I/O requests.
  168.       • Any device control registers and private (beyond base+64 bytes) PCI configuration space on the device 
  169.          need to be saved.  Apple System SW will save/restore only the first 64 bytes of the device's PCI 
  170.          configuration space.  The driver is responsible for saving (and restoring) any other volatile memory 
  171.          on the device.
  172.       • If the device is capable of operating in a low power mode, then set the device to operate in the lowest 
  173.          power mode that is feasible for the device.
  174.       • Return noErr when exiting the Power Handler.
  175.  
  176. After each PCI slot device driver has saved the device’s state, the PCI bus power will be removed.
  177.  
  178.  
  179. B.   Wake
  180. When the system is coming out of Sleep and making progress toward the On state, the Power Manager will service the Power Handler queues before servicing any registered classic SleepQProcs.  When the Handler receives a kSleepWakeUp message, it needs to reverse any action taken to bring its device to the Sleep state.  Specifically:
  181.  
  182.       • Restore any saved control registers and/or any private (beyond base+64 bytes) PCI configuration space.
  183.       • Enable the device’s interrupt(s).
  184.       • Restart any pending I/O that was suspended during the kSleepDemand message.
  185.  
  186.  
  187. C.   Potential problems
  188. Unlike the classic SleepQProcs, Power Handlers are not allowed to allocate memory or use any system services which may cause memory to move. Additionally, Handlers should not perform any action that would cause a page fault.  Finally, remember that CPU interrupts are disabled when a Power Handler is called with a kSleepDemand, kDozeDemand, or kSuspendDemand message.
  189.  
  190.  
  191. V.      Notes
  192. (1) See “PCI Bus Power Management Interface Specification”, v1.1, Dec 1998, PCI Special Interest Group.
  193. (2) See “PCI Power Management Working Group ECR”, May 1997, Intel Corporation.
  194.